package zuo.biao.library.ui;

import ohos.aafwk.content.Intent;
import ohos.agp.colors.RgbColor;
import ohos.agp.components.*;
import ohos.agp.components.element.Element;
import ohos.agp.components.element.ShapeElement;
import ohos.agp.render.Paint;
import ohos.agp.text.Font;
import ohos.agp.utils.Color;
import ohos.agp.utils.TextAlignment;
import ohos.app.Context;
import zuo.biao.library.ResourceTable;
import zuo.biao.library.util.ContactUtil;
import zuo.biao.library.util.ResTUtil;
import zuo.biao.library.util.ScreenUtil;
import zuo.biao.library.util.UiTUtil;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Locale;

/*
 * Copyright (C) 2021 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * 多功能通用弹框
 */
public class EditTextInfoWindow extends ohos.agp.window.dialog.CommonDialog implements Component.ClickedListener {
    private static final String TAG = EditTextInfoWindow.class.getSimpleName();
    //Data数据区(存在数据获取或处理代码，但不存在事件监听代码)<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<


    private static final String INTENT_PACKAGE_NAME = "INTENT_PACKAGE_NAME";
    /**
     *TYPE_NICK
     */
    protected static final int TYPE_NICK = 200 + ContactUtil.TYPE_NICK;
    /**
     *TYPE_NAME
     */
    protected static final int TYPE_NAME = 200 + ContactUtil.TYPE_NAME;
    /**
     *TYPE_PHONE
     */
    protected static final int TYPE_PHONE = 200 + ContactUtil.TYPE_PHONE;
    /**
     *TYPE_WEBSITE
     */
    protected static final int TYPE_WEBSITE = 200 + ContactUtil.TYPE_WEBSITE;
    /**
     *TYPE_EMAIL
     */
    protected static final int TYPE_EMAIL = 200 + ContactUtil.TYPE_EMAIL;
    /**
     *TYPE_FAX
     */
    protected static final int TYPE_FAX = 200 + ContactUtil.TYPE_FAX;
    /**
     *TYPE_USUALADDRESS
     */
    protected static final int TYPE_USUALADDRESS = 200 + ContactUtil.TYPE_USUALADDRESS;
    /**
     *TYPE_MAILADDRESS
     */
    protected static final int TYPE_MAILADDRESS = 200 + ContactUtil.TYPE_MAILADDRESS;
    /**
     *TYPE_SCHOOL
     */
    protected static final int TYPE_SCHOOL = 200 + ContactUtil.TYPE_SCHOOL;
    /**
     *TYPE_COMPANY
     */
    protected static final int TYPE_COMPANY = 200 + ContactUtil.TYPE_COMPANY;
    /**
     *TYPE_PROFESSION
     */
    protected static final int TYPE_PROFESSION = 200 + ContactUtil.TYPE_PROFESSION;
    /**
     *TYPE_NOTE
     */
    protected static final int TYPE_NOTE = 200 + ContactUtil.TYPE_NOTE;
    /**
     *INTENT_TYPE
     */
    protected static final String INTENT_TYPE = "INTENT_TYPE";
    /**
     *INTENT_KEY
     */
    protected static final String INTENT_KEY = "INTENT_KEY";
    /**
     *INTENT_VALUE
     */
    protected static final String INTENT_VALUE = "INTENT_VALUE";
    boolean textAllCaps = true;
    private Text tvMinMax;
    private TextField input;
    private ListContainer listContainer;
    private OnPositiveListener listener;
    Builder builder;
    private Text tvTitle;
    private Image ivLogo;
    private DirectionalLayout titleFrame;
    private Text tvContent;
    private Button btnPositive;
    private Button btnNeutral;
    private Button btnNegative;

    /**
     * @param context 上下文
     * @param key key
     * @param value value
     * @return Intent
     */
    public static Intent createIntent(Context context, String key, String value,EditTextInfoWindow.InputCallback sureCall,EditTextInfoWindow.OnPositiveListener cancelCall) {
        return createIntent(context, key, value, "zuo.biao.library",sureCall,cancelCall);
    }
    /**
     * @param context 上下文
     * @param key key
     * @param value value
     * @param packageName packageName
     * @return  Intent
     */
    public static Intent createIntent(Context context, String key, String value, String packageName,EditTextInfoWindow.InputCallback sureCall,EditTextInfoWindow.OnPositiveListener cancelCall) {
        return createIntent(context, 0, key, value, packageName,sureCall,cancelCall);
    }
    /**
     * @param context 上下文
     * @param type type
     * @param key key
     * @param value value
     * @return Intent
     */
    public static Intent createIntent(Context context, int type, String key, String value,EditTextInfoWindow.InputCallback sureCall,EditTextInfoWindow.OnPositiveListener cancelCall) {
        return createIntent(context, type, key, value, "zuo.biao.library",sureCall,cancelCall);
    }
    /**
     * @param context 上下文
     * @param type type
     * @param key key
     * @param value value
     * @param packageName type == TYPE_MAILADDRESS || type == TYPE_USUALADDRESS时必须不为空
     * @return
     */
    public static Intent createIntent(Context context, int type, String key, String value, String packageName,EditTextInfoWindow.InputCallback sureCall,EditTextInfoWindow.OnPositiveListener cancelCall) {
        new EditTextInfoWindow.Builder(context)
                .title("输入框")
                .inputType()
                .inputRange()
                .input(
                        key,
                        value,
                        false,
                        sureCall)
                .positiveText(
                        "确定",
                        cancelCall)
                .negativeText("取消")
                .show();
        return new Intent();
    }

    private EditTextInfoWindow(Builder builder) {
        super(builder.getContext());
        this.builder = builder;

        ComponentContainer rootLayout =
                (ComponentContainer)
                        LayoutScatter.getInstance(builder.getContext()).parse(getInflateLayout(builder), null, false);

        setSize(ScreenUtil.getScreenWidth(builder.getContext()) * 4 / 5, ComponentContainer.LayoutConfig.MATCH_CONTENT);
        prepareDialogView(rootLayout, builder);
        setContentCustomComponent(rootLayout);
    }



    @Override
    protected void onCreate() {
        super.onCreate();
    }

    private void prepareDialogView(ComponentContainer rootLayout, Builder builder) {
        // Retrieve references to views

        initView(rootLayout);

        initData(rootLayout);

        if (null != builder.negativeText && btnNegative != null) {
            btnNegative.setFont(builder.mediumFont);
            String text = builder.negativeText.toString() != null ? builder.negativeText.toString() : "";
            if (textAllCaps && !text.equals("")) {
                text = text.toUpperCase((Locale.ROOT));
            }
            btnNegative.setText(text);
            btnNegative.setTextColor(
                    new Color(ResTUtil.getColor(builder.getContext(), ResourceTable.Color_colorAccent)));
            btnNegative.setTextAlignment(TextAlignment.END);
            btnNegative.setTag(DialogTAction.NEGATIVE);
            btnNegative.setClickedListener(this);
        }

        if (null != builder.neutralText && btnNeutral != null) {
            btnNeutral.setFont(builder.mediumFont);
            String text = builder.neutralText.toString() != null ? builder.neutralText.toString() : "";
            if (textAllCaps && !text.equals("")) {
                text = text.toUpperCase((Locale.ROOT));
            }
            btnNeutral.setText(text);
            btnNeutral.setTextColor(
                    new Color(ResTUtil.getColor(builder.getContext(), ResourceTable.Color_colorAccent)));
            btnNeutral.setTextAlignment(TextAlignment.CENTER);
            btnNeutral.setTag(DialogTAction.NEUTRAL);
            btnNeutral.setClickedListener(this);
        }

        if (listContainer != null && builder.baseItemProvider == null) {
            ItemProvider provider = new ItemProvider(builder.getContext(), builder.items);
            listContainer.setItemProvider(provider);
            listContainer.setItemClickedListener(
                    new ListContainer.ItemClickedListener() {
                        @Override
                        public void onItemClicked(
                                ListContainer listContainer, Component component, int position, long l) {
                            if (builder.autoDismiss) {
                                // If auto dismiss is enabled, dismiss the dialog when a list item is selected
                                hide();
                            }
                            if (builder.listCallback != null) {
                                builder.listCallback.onSelection(
                                        EditTextInfoWindow.this, component, position, builder.items.get(position));
                            }
                        }
                    });
        }

        invalidateList();
        setupInputDialog(builder, rootLayout);
    }

    private void initView(ComponentContainer rootLayout) {
        tvTitle = UiTUtil.getComponent(rootLayout, ResourceTable.Id_title);
        ivLogo = UiTUtil.getComponent(rootLayout, ResourceTable.Id_icon);
        titleFrame = UiTUtil.getComponent(rootLayout, ResourceTable.Id_titleFrame);
        tvContent = UiTUtil.getComponent(rootLayout, ResourceTable.Id_content);
        listContainer = UiTUtil.getComponent(rootLayout, ResourceTable.Id_listContainer);

        // Button views initially used by checkIfStackingNeeded()
        btnPositive = UiTUtil.getComponent(rootLayout, ResourceTable.Id_btnPositive);
        btnNeutral = UiTUtil.getComponent(rootLayout, ResourceTable.Id_btnNeutral);
        btnNegative = UiTUtil.getComponent(rootLayout, ResourceTable.Id_btnNegative);


        // Don't allow the submit button to not be shown for input dialogs
        if (builder.inputCallback != null && builder.positiveText == null) {
            builder.positiveText = "确定";
        }

        // Set up the initial visibility of action buttons based on whether or not text was set
        if (btnPositive != null) {
            btnPositive.setVisibility(builder.positiveText != null ? Component.VISIBLE : Component.HIDE);
        }
        if (btnNeutral != null) {
            btnNeutral.setVisibility(builder.neutralText != null ? Component.VISIBLE : Component.HIDE);
        }
        if (btnNegative != null) {
            btnNegative.setVisibility(builder.negativeText != null ? Component.VISIBLE : Component.HIDE);
        }

        if (ivLogo != null) {
            ivLogo.setVisibility(Component.VISIBLE);
            ivLogo.setImageElement(builder.icon);
        }
    }

    private void initData(ComponentContainer rootLayout) {
        Paint paint = new Paint();
        paint.setColor(new Color(Color.GRAY.getValue()));
        rootLayout.invalidate();

        initTextData();


        if (null != builder.positiveText && btnPositive != null) {
            btnPositive.setTextColor(
                    new Color(ResTUtil.getColor(builder.getContext(), ResourceTable.Color_colorAccent)));
            btnPositive.setFont(builder.mediumFont);
            String text = builder.positiveText.toString() != null ? builder.positiveText.toString() : "";
            if (textAllCaps && !text.equals("")) {
                text = text.toUpperCase((Locale.ROOT));
            }
            btnPositive.setText(text);
            btnPositive.setTextAlignment(TextAlignment.START);
            btnPositive.setTag(DialogTAction.POSITIVE);
            btnPositive.setClickedListener(
                    new Component.ClickedListener() {
                        @Override
                        public void onClick(Component component) {
                            builder.listener.onClick(component);
                            hide();
                            destroy();
                        }
                    });
        }
    }

    private void initTextData() {
        // Setup title and title frame
        if (tvTitle != null) {
            tvTitle.setFont(builder.mediumFont);
            tvTitle.setTextColor(
                    new Color(ResTUtil.getColor(builder.getContext(), ResourceTable.Color_material_black)));
            tvTitle.setTextAlignment(TextAlignment.START);

            if (builder.title == null) {
                if (titleFrame != null) {
                    titleFrame.setVisibility(Component.HIDE);
                }
            } else {
                tvTitle.setText(builder.title.toString());
                if (titleFrame != null) {
                    titleFrame.setVisibility(Component.VISIBLE);
                }
            }
        }

        if (tvContent != null) {
            tvContent.setLineSpacing(0f, 1.2f);
            tvContent.setTextColor(new Color(ResTUtil.getColor(builder.getContext(), ResourceTable.Color_md_gray)));
            tvContent.setTextAlignment(TextAlignment.START);

            if (builder.content != null) {
                tvContent.setText(builder.content.toString());
                tvContent.setVisibility(Component.VISIBLE);
            } else {
                tvContent.setVisibility(Component.HIDE);
            }
        }
    }

    private void setupInputDialog(Builder builder, final ComponentContainer rootView) {
        input = (TextField) rootView.findComponentById(ResourceTable.Id_input);
        if (input == null) {
            return;
        }
        if (builder.inputPrefill != null) {
            input.setText(builder.inputPrefill.toString());
        }
        setInternalInputCallback();
        input.setHint(builder.inputHint.toString());
        input.setMaxTextLines(1);
        input.setTextColor(new Color(ResTUtil.getColor(builder.getContext(), ResourceTable.Color_material_black)));
        if (builder.inputType != -1) {
            input.setTextInputType(builder.inputType);
        }
        ShapeElement shapeElement = new ShapeElement();
        shapeElement.setShape(ShapeElement.LINE);
        shapeElement.setStroke(
                5, RgbColor.fromArgbInt(ResTUtil.getColor(builder.getContext(), ResourceTable.Color_colorAccent)));
        input.setBasement(shapeElement);

        tvMinMax = (Text) rootView.findComponentById(ResourceTable.Id_minMax);
        if (builder.inputMinLength > 0 || builder.inputMaxLength > -1) {
            invalidateInputMinMaxIndicator(input.getText().length());
        } else {
            tvMinMax.setVisibility(Component.HIDE);
            tvMinMax = null;
        }
    }

    @Override
    public void hide() {
        super.hide();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
    }

    @Override
    public void onClick(Component component) {
        hide();
        destroy();
    }

    /**
     * builder
     */
    public static class Builder {
        private Context context;
        InputCallback inputCallback;
        List<String> items;
        ItemProvider baseItemProvider;
        String inputPrefill;
        String inputHint;
        String positiveText;
        String neutralText;
        String negativeText;
        String title;
        String content;
        Element icon;
        Font regularFont;
        Font mediumFont;
        ListCallback listCallback;
        OnPositiveListener listener;
        int inputType = -1;
        int inputMinLength = -1;
        int inputMaxLength = -1;
        int inputRangeErrorColor = 0;
        boolean inputAllowEmpty;
        boolean autoDismiss = true;

        public Builder(Context context) {
            this.context = context;

            if (this.mediumFont == null) {
                try {
                    this.mediumFont = new Font.Builder("sans-serif-medium").build();
                    this.mediumFont = Font.DEFAULT;
                } catch (Throwable ignored) {
                    this.mediumFont = Font.DEFAULT_BOLD;
                }
            }
            if (this.regularFont == null) {
                try {
                    this.mediumFont = new Font.Builder("sans-serif").build();
                    this.mediumFont = Font.DEFAULT;
                } catch (Throwable ignored) {
                    this.regularFont = Font.SANS_SERIF;
                    if (this.regularFont == null) {
                        this.regularFont = Font.DEFAULT;
                    }
                }
            }
        }

        /**
         * 上下文
         * @return c
         */
        public final Context getContext() {
            return context;
        }

        /**
         * 设置title
         * @param titleRes resId
         * @return b
         */
        public EditTextInfoWindow.Builder title(String titleRes) {
            this.title = titleRes;
            return this;
        }

        /**
         * 设置icon
         *
         * @param iconRes id
         * @return b
         */
        public EditTextInfoWindow.Builder icon(int iconRes) {
            this.icon = ResTUtil.getPixelMapDrawable(context, iconRes);
            return this;
        }

        /**
         * 设置内容
         * @param contentRes r
         * @return b
         */
        public EditTextInfoWindow.Builder content(String contentRes) {
            this.content = contentRes;
            return this;
        }

        /**
         * 设置item
         * @param items i
         * @return b
         */
        public EditTextInfoWindow.Builder items(String... items) {
            this.items = new ArrayList<>();
            Collections.addAll(this.items, items);
            return this;
        }

        /**
         * 设置监听
         * @param callback c
         * @return r
         */
        public EditTextInfoWindow.Builder itemsCallback(EditTextInfoWindow.ListCallback callback) {
            this.listCallback = callback;
            return this;
        }

        /**
         * 设置确定
         * @param positiveRes 确定
         * @param listener 监听
         * @return b
         */
        public EditTextInfoWindow.Builder positiveText(String positiveRes, OnPositiveListener listener) {
            if (positiveRes == null) {
                return this;
            }
            this.positiveText = positiveRes;
            this.listener = listener;
            return this;
        }

        /**
         * 设置取消
         * @param id 取消
         * @return b
         */
        public EditTextInfoWindow.Builder negativeText(String id) {
            this.negativeText = id;
            return this;
        }

        /**
         * 设置类型
         * @return b
         */
        public EditTextInfoWindow.Builder inputType() {
            this.inputType = InputAttribute.PATTERN_TEXT;
            return this;
        }

        /**
         * 设置类型
         * @return b
         */
        public EditTextInfoWindow.Builder inputRange() {
            this.inputMinLength = 2;
            this.inputMaxLength = 16;
            this.inputRangeErrorColor = ResTUtil.getColor(context, ResourceTable.Color_t_edittext_error);
            if (this.inputMinLength > 0) {
                this.inputAllowEmpty = false;
            }
            return this;
        }

        /**
         * 类型
         * @param hint hint
         * @param prefill prefill
         * @param allowEmptyInput allowEmptyInput
         * @param callback callback
         * @return b
         */
        public EditTextInfoWindow.Builder input(
                String hint, String prefill, boolean allowEmptyInput, InputCallback callback) {
            this.inputCallback = callback;
            this.inputHint = hint;
            this.inputPrefill = prefill;
            this.inputAllowEmpty = allowEmptyInput;
            return this;
        }

        /**
         * 展示show
         */
        public void show() {
            new EditTextInfoWindow(this).show();
        }
    }

    /**
     * item 选择监听
     */
    public interface ListCallback {
        /**
         * 选择结果
         * @param dialog d
         * @param itemView i
         * @param position p
         * @param text t
         */
        void onSelection(EditTextInfoWindow dialog, Component itemView, int position, String text);
    }

    /**
     * input类型监听
     */
    public interface InputCallback {
        /**
         * 输入回调
         * @param dialog d
         * @param input i
         */
        void onInput(EditTextInfoWindow dialog, String input);
    }

    private int getInflateLayout(EditTextInfoWindow.Builder builder) {
        if (builder.inputCallback != null) {
            return ResourceTable.Layout_uilayouts_dependent_layout;
        } else if (builder.items != null || builder.baseItemProvider != null) {
            return ResourceTable.Layout_uilayouts_stack_layout;
        }else {
            return ResourceTable.Layout_uilayouts_directional_layout;
        }
    }

    private void invalidateList() {}

    private void setInternalInputCallback() {
        if (input == null) {
            return;
        }
        input.addTextObserver(
                (soul, i, i1, i2) -> {
                    final int length = soul.length();
                    invalidateInputMinMaxIndicator(length);
                    builder.inputCallback.onInput(EditTextInfoWindow.this, soul);
                });
    }

    private void invalidateInputMinMaxIndicator(int currentLength) {
        if (tvMinMax != null) {
            if (builder.inputMaxLength > 0) {
                tvMinMax.setText(String.format(Locale.getDefault(), "%d/%d", currentLength, builder.inputMaxLength));
                tvMinMax.setVisibility(Component.VISIBLE);
            } else {
                tvMinMax.setVisibility(Component.HIDE);
            }
            if (builder.inputMaxLength > 0) {
                tvMinMax.setTextColor(
                        new Color(ResTUtil.getColor(builder.getContext(), ResourceTable.Color_textColorSecondary)));
            }
        }
    }

    /**
     * 点击确定时监听
     */
    public interface OnPositiveListener {
        /**
         * 回调方法
         * @param component  v
         */
        void onClick(Component component);
    }
}
